#pragma once
#include "node.h"
#include "lefParser.h"
#include "lefStru.h"
#include "pos.h"
#include <map>
#include <vector>
using namespace std;

class element
{
private:
    node* elementNode;
    LEF::cell elementCell;
public:
    element(node* elementNode,LEF::cell elementCell)
    {
        this->elementNode=elementNode,this->elementCell=elementCell;
    }
    node* getnode()
    {
        return this->elementNode;
    }
    LEF::cell getCell()
    {
        return this->elementCell;
    }
};

class layout
{
private:
    nodeManager* manager;
    lefParser lp;
    int width;
    int heigh;
    vector<element> allElement;
    int quadrangleCounter;
public:
    float getInterfaceManhattanDistance(pinRect a,pinRect b)//计算接口间曼哈顿距离
    {
        float x1,y1,x2,y2;
        tie(x1,y1)=a.getMidPos();
        tie(x2,y2)=b.getMidPos();
        return abs(x1-x2)+abs(y1-y2);//C++11支持abs运算浮点数  如有问题应换fabs
    }
    void addElement(node* node,LEF::cell cell)//添加节点
    {
        element tempelement(node,cell);
        allElement.push_back(tempelement);
    }
    //左上->右上->左下->右下初步考虑使用计数器/4的方法解决(看余数)(考虑到元件数大于4的情况)
    pair<float,float> quadrangleLayout(float x,float y,float Recomspacing)
    {
        int counter=quadrangleCounter%4;
        float resultX,resultY;
        switch(counter)
        {
            case 0: //左上
                resultX=x-(Recomspacing/2);
                resultY=y+(Recomspacing/2);
            case 1: //右上
                resultX=x+(Recomspacing/2);
                resultY=y+(Recomspacing/2);
            case 2: //左下
                resultX=x-(Recomspacing/2);
                resultY=y-(Recomspacing/2);
            default: //右下
                resultX=x+(Recomspacing/2);
                resultY=y-(Recomspacing/2);
        }
        quadrangleCounter++;
        return {resultX,resultY};
    }
    //旋转元件取最短曼哈顿距离
    void rotatingElement(LEF::cell obj1,LEF::cell& obj2,int i1,int i2)
    {
        float Ndistance,Sdistance,Wdistance,Edistance;
        pinRect r1=obj1.allPin[i1].allRect[0];
        pinRect r2=obj2.allPin[i2].allRect[0];
        Ndistance=getInterfaceManhattanDistance(r1,r2);
        obj2.setDire("W");
        r2=obj2.allPin[i2].allRect[0];
        Wdistance=getInterfaceManhattanDistance(r1,r2);
        obj2.setDire("W");
        r2=obj2.allPin[i2].allRect[0];
        Sdistance=getInterfaceManhattanDistance(r1,r2);
        obj2.setDire("W");
        r2=obj2.allPin[i2].allRect[0];
        Edistance=getInterfaceManhattanDistance(r1,r2);
        obj2.setDire("W");//方位初始化
        if((Ndistance<=Wdistance)&&(Ndistance<=Sdistance)&&(Ndistance<=Edistance))
        {
            obj2.direction="N";
        }
        else if((Wdistance<=Ndistance)&&(Wdistance<=Sdistance)&&(Wdistance<=Edistance))
        {
            obj2.direction="W";
            obj2.setDire("W");
        }
        else if((Sdistance<=Ndistance)&&(Sdistance<=Wdistance)&&(Sdistance<=Edistance))
        {
            obj2.direction="S";
            obj2.setDire("S");
        }
        else
        {
            obj2.direction="E";
            obj2.setDire("E");
        }
    }
    //遍历检查是否相交与出界
    bool intersectionJudgment(LEF::cell obj,float spacing,float minWidth)
    {
        float centreX1,centreY1,length1,width1;
        float centreX2,centreY2,length2,width2;
        float x11,y11,x12,y12,x21,y21,x22,y22;  //左下右上坐标
        int count=allElement.size();
        bool flag=false;
        LEF::cell tempobj;
        length1=obj.sizeA1;
        width1=obj.sizeA2;
        centreX1=obj.setX;
        centreY1=obj.setY;
        x11=centreX1-length1/2;
        y11=centreY1-width1/2;
        x12=centreX1+length1/2;
        y12=centreY1+width1/2;
        if((x11>width)||(x11<0)||(x12>width)||(x12)<0||(y11>heigh)||(y11<0)||(y12>heigh)||(y12<0))
            return true;
        for(int i=0;i<count;i++)
        {
            tempobj=allElement[i].getCell();
            length2=obj.sizeA1;
            width2=obj.sizeA2;
            centreX2=obj.setX;
            centreY2=obj.setY;
            x21=centreX2-length2/2;
            y21=centreY2-width2/2;
            x22=centreX2+length2/2;
            y22=centreY2+width2/2;
            rect r1(pos(x11,y11),pos(x12,y22));
            rect r2(pos(x21,y21),pos(x22,y22));
            if(r1.isIntersect(r2,spacing,minWidth)) { return true; }
        }
        return false;
    }
    //按照建议间距摆放矩形
    layout(nodeManager* manager, lefParser lp, int width, int heigh) :
        manager(manager), lp(lp), width(width), heigh(heigh)//未完成
    {
        int Vectorcount;
        float Recomspacing=1.0;//目前假设的建议间距  后续调用lp中的建议间距进行替换
        float Adjuststep=0.2;   //目前设置的调整步长
        float focus[]={float(width)/2,float(heigh)/2};//第一个元件应放在版图中心点
        float tempfocus[2];
        float spacing,minWidth;
        map<node*,int> allNode=manager->getNodeMultiplexing();//获取每个node被使用的次数并储存
        int temp=0;
        node* tempnode=NULL;
        line* templine=NULL;
        for(auto i : allNode)   //寻找被使用最多次数的node
        {
            if(i.second>temp)
            {
                temp=i.second;
                tempnode=i.first;
            }
        }
        string type=tempnode->g->getName();
        LEF::cell obj=lp.getCell(type);
        obj.setToLayout(focus[0],focus[1]);
        obj.direction="N";
        addElement(tempnode,obj);   //储存摆放好的节点
        LEF::metal m1=lp.getMetal(1);
        spacing=m1.spacing;
        minWidth=m1.minWidth;
        //进行布局
        Vectorcount=tempnode->inputLine.size();
        for(int i=0;i<Vectorcount;i++)
        {
            templine=(tempnode->inputLine)[i];
            //tempnode=templine->n;
            type=templine->n->g->getName();
            LEF::cell tempobj=lp.getCell(type);
            tie(tempfocus[0],tempfocus[1])=quadrangleLayout(focus[0],focus[1],Recomspacing);
            tempobj.setToLayout(tempfocus[0],tempfocus[1]);
            rotatingElement(obj,tempobj,i,templine->getSub());
            intersectionJudgment(tempobj,spacing,minWidth);
            addElement(templine->n,tempobj);
        }
    }
};
